home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / Dots & Pixels / sources / screenarea.cp < prev    next >
Text File  |  1995-09-29  |  8KB  |  339 lines

  1. #define min( a, b) (((a) < (b)) ? (a) : (b))
  2. #define max( a, b) (((a) > (b)) ? (a) : (b))
  3.  
  4. #include <QuickDraw.h>
  5.  
  6. #include "C_randomizer.h"
  7. #include "screenarea.h"
  8. //
  9. // 941027: significantly increase 'max_error' to 'pseudo-fix' the bug
  10. // with Set/Move/EraseMultiDots. This costs us about 40K extra memory
  11. // per instance of 'screenarea', but what the heck… Alternatively we
  12. // could just allocate one common 'waste_area'.
  13. //
  14. // const int screenarea::max_error = 20;
  15. //
  16. const int screenarea::max_error = 20000;
  17.  
  18. screenarea::screenarea( int numbits, screen_position where)
  19.     : size( 1 << numbits)
  20.     , half_size( 1 << (numbits - 1))
  21.     , shiftbits( 2 * numbits - 9)
  22.     , coord_shift( 16 - numbits)
  23. {
  24.     GDHandle thescreendevice = GetMainDevice();
  25.     const PixMapHandle pix_of_current = (**thescreendevice).gdPMap;
  26.     const Rect screenrect = (**pix_of_current).bounds;
  27.     const int half_screenHeight = (screenrect.bottom - screenrect.top)  / 2;
  28.     const int half_screenWidth  = (screenrect.right  - screenrect.left) / 2;
  29.     
  30.     int ypos = half_screenHeight - half_size;
  31.     int xpos = 0;
  32.  
  33.     switch( where)
  34.     {
  35.         case centered:
  36.             xpos = half_screenWidth - half_size;
  37.             break;
  38.         
  39.         case left_side:
  40.             xpos = half_screenWidth - (size + 48);
  41.             break;
  42.             
  43.         case right_side:
  44.             xpos = half_screenWidth + 48;
  45.             break;
  46.             
  47.         default:
  48.             DebugStr( "\pInvalid position in 'live_flow' constructor");
  49.     }
  50.     init( xpos, ypos);
  51. }
  52.  
  53. screenarea::~screenarea()
  54. {
  55.     screen -= half_size;
  56.     delete screen;
  57.     waste_area -= max_error;
  58.     delete waste_area;
  59. }
  60.  
  61. void screenarea::fill( const int value)
  62. {
  63.     for( int y = -half_size; y < half_size; y++)
  64.     {
  65.         unsigned char *row = screen[ y] - half_size;
  66.         for( int x = 0; x < size; x++)
  67.         {
  68.             *row++ = value;
  69.         }
  70.     }
  71. }
  72.  
  73. void screenarea::add_circular_mask( void)
  74. {
  75.     //
  76.     // We assume colors 0 through 127 to form a nice ramp from white
  77.     // to black and all other colors to be black. That way color 0
  78.     // is white and color 255 is black (as is customary on the Mac)
  79.     // _and_ we can make a perfectly black screen which turns into a
  80.     // grayscale image by adding 0x80 to the pixels.
  81.     //
  82.     // Note: we use (x+1) * (x+1) = x2 + 2 * x + 1 to speed things up
  83.     //
  84.     int y_squared = -half_size * -half_size;
  85.  
  86.     const int square_limit = half_size * half_size;
  87.     
  88.     for( int y = -half_size; y < half_size; y++)
  89.     {
  90.         unsigned char *row = screen[ y];
  91.         int square_sum = y_squared + -half_size * -half_size;
  92.         
  93.         for( int x = -half_size; x < half_size; x++)
  94.         {            
  95.             if( square_sum >= square_limit)
  96.             {
  97.                 row[ x] = 255;    // always stays black
  98.             } else {
  99.                 row[ x] = (unsigned char)(0x80 + (square_sum >> shiftbits));
  100.             }
  101.             square_sum += (x << 1) + 1;
  102.         }
  103.         y_squared += (y << 1) + 1;
  104.     }
  105. }
  106.  
  107. void screenarea::add_rectangular_mask( int mask_size)
  108. {
  109.     const int mask_limit = half_size - mask_size;
  110.     //
  111.     // We assume colors 0 through 127 to form a nice ramp from white
  112.     // to black and all other colors to be black. That way color 0
  113.     // is white and color 255 is black (as is customary on the Mac)
  114.     // _and_ we can make a perfectly black screen which turns into a
  115.     // grayscale image by adding 0x80 to the pixels. => write 255
  116.     // to pixels which must stay black at all times, write 128 to
  117.     // pixels which may turn white.
  118.     //
  119.     for( int y = -half_size; y < half_size; y++)
  120.     {
  121.         unsigned char *row = screen[ y];
  122.         const int y_at_outside = (y < -mask_limit) || (y >= mask_limit);
  123.         if( y_at_outside)
  124.         {
  125.             for( int x = -half_size; x < half_size; x++)
  126.             {
  127.                 row[ x] = 255;
  128.             }
  129.         } else {
  130.             for( int x = -half_size; x < half_size; x++)
  131.             {            
  132.                 const int x_at_outside = (x < -mask_limit) || (x >= mask_limit);
  133.                 if( x_at_outside)
  134.                 {
  135.                     row[ x] = 255;    // always stays black
  136.                 } else {
  137.                     row[ x] = 128;
  138.                 }
  139.             }
  140.         }
  141.     }
  142. }
  143.  
  144. void screenarea::add_fixation_dot( const int disparity)
  145. {
  146.     add_big_dot( 0, 0, disparity);
  147. }
  148.  
  149. void screenarea::add_stereo_cues( const int disparity)
  150. {
  151.     const int one_q_size = half_size / 2;
  152.     
  153.     add_big_dot(  one_q_size,  one_q_size, disparity);
  154.     add_big_dot(  one_q_size, -one_q_size, disparity);
  155.     add_big_dot( -one_q_size,  one_q_size, disparity);
  156.     add_big_dot( -one_q_size, -one_q_size, disparity);
  157. }
  158.  
  159. void screenarea::compass2offsets( const char *compass, int *offsets, int *maxnum)
  160. {
  161.     const int bovengrens = 500;
  162.     int *temp_result = new int[ bovengrens];    // more than enough?
  163.     
  164.     int curoffset  = 0;
  165.     int min_offset = 0;
  166.     int max_offset = 0;
  167.     int curindex   = 0;
  168.     int numtoset   = 0;
  169.     int stepoffset = 0;
  170.     int mark_them  = false;
  171.  
  172.     int index = 0;
  173.     while( compass[ index] != 0)
  174.     {
  175.         switch( compass[ index])
  176.         {
  177.             case '0':    case '1':    case '2':    case '3':    case '4':
  178.             case '5':    case '6':    case '7':    case '8':    case '9':
  179.                 numtoset *= 10;
  180.                 numtoset += compass[ index] - '0';
  181.                 break;
  182.  
  183.             case 'E':
  184.                 mark_them = true;
  185.             case 'e':
  186.                 stepoffset = 1;
  187.                 break;
  188.  
  189.             case 'S':
  190.                 mark_them = true;
  191.             case 's':
  192.                 stepoffset = rowBytes;
  193.                 break;
  194.  
  195.             case 'W':
  196.                 mark_them = true;
  197.             case 'w':
  198.                 stepoffset = -1;
  199.                 break;
  200.  
  201.             case 'N':
  202.                 mark_them = true;
  203.             case 'n':
  204.                 stepoffset = -rowBytes;
  205.                 break;
  206.  
  207.             case '.':
  208.                 numtoset = 1;    // replace '3.' by '.' ('3.' doesn't make sense)
  209.                 mark_them = true;
  210.                 break;
  211.  
  212.             default:
  213.                 DebugStr( "\pInvalid character in 'compasses' string");
  214.         }
  215.         if( (stepoffset != 0) || (mark_them == true))
  216.         {
  217.             if( numtoset == 0)
  218.             {
  219.                 numtoset = 1;
  220.             }
  221.             if( mark_them)
  222.             {
  223.                 mark_them = false;
  224.                 for( int i = 0; i < numtoset; i++)
  225.                 {
  226.                     min_offset = min( curoffset, min_offset);
  227.                     max_offset = max( curoffset, max_offset);
  228.                     temp_result[ curindex] = curoffset;
  229.                     curindex += 1;
  230.                     curoffset += stepoffset;
  231.                 }
  232.             } else {
  233.                 curoffset += numtoset * stepoffset;
  234.             }
  235.             numtoset   = 0;
  236.             stepoffset = 0;
  237.         }
  238.         index += 1;
  239.     }
  240.     //
  241.     // We now have computed both the actual number of offsets (in curindex),
  242.     // the actual offsets (in temp_result[ 0] through temp_result[ curindex - 1]),
  243.     // and the range of offsets encountered (in min_offset and max_offset, provided
  244.     // that zero is actually inside the range of offsets encountered).
  245.     //
  246.     if( min_offset <= -max_error)
  247.     {
  248.         DebugStr( "\pscreenarea::compass2offsets : minimal offset too small");
  249.     }
  250.     if( max_offset >= max_error)
  251.     {
  252.         DebugStr( "\pscreenarea::compass2offsets : maximal offset too large");
  253.     }
  254.     if( offsets != 0)
  255.     {
  256.         const int numtocopy = (*maxnum < curindex) ? *maxnum : curindex;
  257.         for( int i = 0; i < numtocopy; i++)
  258.         {
  259.             offsets[ i] = temp_result[ i];
  260.         }
  261.     }
  262.     *maxnum = curindex;
  263.     delete temp_result;
  264. }
  265.  
  266. void screenarea::init( int xpos, int ypos)
  267. {
  268.     screen = new unsigned char *[ size];
  269.     waste_area = new unsigned char[ size + 2 * max_error];
  270.     waste_area += max_error;
  271.  
  272.     GDHandle thescreendevice = GetMainDevice();
  273.     const PixMapHandle pix_of_current = (**thescreendevice).gdPMap;
  274.  
  275.     const Rect screenrect = (**pix_of_current).bounds;
  276.     
  277.     rowBytes = ((**pix_of_current).rowBytes) & 0x1FFF;
  278.     
  279.     const int screenHeight = screenrect.bottom - screenrect.top;
  280.     const int screenWidth  = screenrect.right  - screenrect.left;
  281.  
  282.     unsigned char *screenBits = (unsigned char *)(**pix_of_current).baseAddr;
  283.     //
  284.     // safety
  285.     //
  286.     if( xpos + size >= screenWidth)
  287.     {
  288.         xpos = screenWidth - size;
  289.     }
  290.     if( xpos < 0)
  291.     {
  292.         xpos = 0;
  293.     }    
  294.     for( int i = 0; i < size; i++)
  295.     {
  296.         const int ypos_plus_i = ypos + i;
  297.         
  298.         if( (ypos_plus_i < 0) || (ypos_plus_i >= screenHeight))
  299.         {
  300.             screen[ i] = waste_area;
  301.         } else {
  302.             screen[ i] = screenBits + (ypos_plus_i * rowBytes) + xpos;
  303.         }
  304.     }
  305.     //
  306.     // We have now allocated the array to point at the start of the rows.
  307.     // Change this to point halfway into the rows:
  308.     //
  309.     #ifdef __MWERKS__
  310.         for( int i = 0; i < size; i++)
  311.     #else
  312.         for( i = 0; i < size; i++)
  313.     #endif
  314.     {
  315.         screen[ i] += half_size;
  316.     }
  317.     screen += half_size;
  318. }
  319.  
  320. void screenarea::add_big_dot( const int x, const int y, const int disparity)
  321. {
  322.     const int left_disparity  = disparity / 2;
  323.     const int right_disparity = left_disparity - disparity;
  324.  
  325.     unsigned char *screen_y = screen[ y];
  326.     
  327.     screen_y[ x + left_disparity     ] -= 1;
  328.     screen_y[ x + right_disparity    ] -= 8;
  329.     screen_y[ x + left_disparity  + 1] -= 1;
  330.     screen_y[ x + right_disparity + 1] -= 8;
  331.  
  332.     screen_y = screen[ y + 1];
  333.  
  334.     screen_y[ x + left_disparity     ] -= 1;
  335.     screen_y[ x + right_disparity    ] -= 8;
  336.     screen_y[ x + left_disparity  + 1] -= 1;
  337.     screen_y[ x + right_disparity + 1] -= 8;
  338. }
  339.